/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 */

package org.alfresco.jlan.smb.nt;

/**
 * NT IO Control Codes Class
 *
 * @author gkspencer
 */
public class NTIOCtl {

  //	Device type codes

  public static final int DeviceBeep							=	0x0001;
  public static final int DeviceCDRom							= 0x0002;
  public static final int DeviceCDRomFileSystem		= 0x0003;
  public static final int DeviceController				= 0x0004;
  public static final int DeviceDataLink					= 0x0005;
  public static final int DeviceDFS								= 0x0006;
  public static final int DeviceDisk							= 0x0007;
  public static final int DeviceDiskFileSystem		= 0x0008;
  public static final int DeviceFileSystem				= 0x0009;
  public static final int DeviceInportPort				= 0x000A;
  public static final int DeviceKeyboard					= 0x000B;
  public static final int DeviceMailSlot					= 0x000C;
  public static final int DeviceMidiIn						= 0x000D;
  public static final int DeviceMidiOut						= 0x000E;
  public static final int DeviceMouse							= 0x000F;
  public static final int DeviceMultiUNCProvider	= 0x0010;
  public static final int DeviceNamedPipe					= 0x0011;
  public static final int DeviceNetwork						= 0x0012;
  public static final int DeviceNetworkBrowser		= 0x0013;
  public static final int DeviceNetworkFileSystem = 0x0014;
  public static final int DeviceNull							= 0x0015;
  public static final int DeviceParallelPort			= 0x0016;
  public static final int DevicePhysicalNetCard		= 0x0017;
  public static final int DevicePrinter						= 0x0018;
  public static final int DeviceScanner						= 0x0019;
  public static final int DeviceSerialMousePort		= 0x001A;
  public static final int DeviceSerialPort				= 0x001B;
  public static final int DeviceScreen						= 0x001C;
  public static final int DeviceSound							= 0x001D;
  public static final int DeviceStreams						= 0x001E;
  public static final int DeviceTape							= 0x001F;
  public static final int DeviceTapeFileSystem		= 0x0020;
  public static final int DeviceTransport					= 0x0021;
  public static final int DeviceUnknown						= 0x0022;
  public static final int DeviceVideo							= 0x0023;
  public static final int DeviceVirtualDisk				= 0x0024;
  public static final int DeviceWaveIn						= 0x0025;
  public static final int DeviceWaveOut						= 0x0026;
  public static final int Device8042Port					= 0x0027;
  public static final int DeviceNetworkRedirector	= 0x0028;
  public static final int DeviceBattery						= 0x0029;
  public static final int DeviceBusExtender				= 0x002A;
  public static final int DeviceModem							= 0x002B;
  public static final int DeviceVDM								= 0x002C;
  public static final int DeviceMassStorage				= 0x002D;
  public static final int DeviceSMB								= 0x002E;
  public static final int DeviceKS								= 0x002F;
  public static final int DeviceChanger						= 0x0030;
  public static final int DeviceSmartCard					= 0x0031;
  public static final int DeviceACPI							= 0x0032;
  public static final int DeviceDVD								= 0x0033;
  public static final int DeviceFullScreenVideo		= 0x0034;
  public static final int DeviceDFSFileSystem			= 0x0035;
  public static final int DeviceDFSVolume					= 0x0036;

  //	Method types for I/O and filesystem controls

  public static final int MethodBuffered					= 0;
  public static final int MethodInDirect					= 1;
  public static final int MethodOutDirect					= 2;
  public static final int MethodNeither						= 3;

  //	Access check types

  public static final int AccessAny								= 0;
  public static final int AccessRead							= 0x0001;
  public static final int AccessWrite							= 0x0002;

  //	Filesystem function codes

  public static final int FsCtlRequestOplockLevel1	= 0;
  public static final int FsCtlRequestOplockLevel2	= 1;
  public static final int FsCtlRequestBatchOplock 	= 2;
  public static final int FsCtlOplockBreakAck     	= 3;
  public static final int FsCtlOpBatchAckClosePend	= 4;
  public static final int FsCtlOplockBreakNotify  	= 5;
  public static final int FsCtlLockVolume         	= 6;
  public static final int FsCtlUnlockVolume       	= 7;
  public static final int FsCtlDismountVolume     	= 8;
  public static final int FsCtlIsVolumeMounted    	= 10;
  public static final int FsCtlIsPathnameValid    	= 11;
  public static final int FsCtlMarkVolumeDirty    	= 12;
  public static final int FsCtlQueryRetrievalPtrs 	= 14;
  public static final int FsCtlGetCompression     	= 15;
  public static final int FsCtlSetCompression     	= 16;
  public static final int FsCtlMarkAsSystemHive   	= 19;
  public static final int FsCtlOplockBreakAck2    	= 20;
  public static final int FsCtlInvalidateVolumes  	= 21;
  public static final int FsCtlQueryFatBPB        	= 22;
  public static final int FsCtlRequestFilterOplock	= 23;
  public static final int FsCtlFileSysGetStats    	= 24;
  public static final int FsCtlGetNTFSVolumeData  	= 25;
  public static final int FsCtlGetNTFSFileRecord  	= 26;
  public static final int FsCtlGetVolumeBitmap    	= 27;
  public static final int FsCtlGetRetrievalPtrs   	= 28;
  public static final int FsCtlMoveFile           	= 29;
  public static final int FsCtlIsVolumeDirty      	= 30;
  public static final int FsCtlGetHFSInfo         	= 31;
  public static final int FsCtlAllowExtenDasdIO   	= 32;
  public static final int FsCtlReadPropertyData   	= 33;
  public static final int FsCtlWritePropertyData  	= 34;
  public static final int FsCtlFindFilesBySID     	= 35;
  public static final int FsCtlDumpPropertyData   	= 37;
  public static final int FsCtlSetObjectId        	= 38;
  public static final int FsCtlGetObjectId        	= 39;
  public static final int FsCtlDeleteObjectId     	= 40;
  public static final int FsCtlSetReparsePoint    	= 41;
  public static final int FsCtlGetReparsePoint    	= 42;
  public static final int FsCtlDeleteReparsePoint 	= 43;
  public static final int FsCtlEnumUsnData        	= 44;
  public static final int FsCtlSecurityIdCheck    	= 45;
  public static final int FsCtlReadUsnJournal     	= 46;
  public static final int FsCtlSetObjectIdExtended	= 47;
  public static final int FsCtlCreateOrGetObjectId	= 48;
  public static final int FsCtlSetSparse          	= 49;
  public static final int FsCtlSetZeroData        	= 50;
  public static final int FsCtlQueryAllocRanges   	= 51;
  public static final int FsCtlEnableUpgrade      	= 52;
  public static final int FsCtlSetEncryption      	= 53;
  public static final int FsCtlEncryptionFsCtlIO  	= 54;
  public static final int FsCtlWriteRawEncrypted  	= 55;
  public static final int FsCtlReadRawEncrypted   	= 56;
  public static final int FsCtlCreateUsnJournal   	= 57;
  public static final int FsCtlReadFileUsnData    	= 58;
  public static final int FsCtlWriteUsnCloseRecord	= 59;
  public static final int FsCtlExtendVolume       	= 60;

  // Base value for custom control codes

  public static final int FsCtlCustom                 = 0x800;

  /**
   * Extract the device type from an I/O control code
   *
   * @param ioctl int
   * @return int
   */
  public final static int getDeviceType(int ioctl) {
    return ( ioctl >> 16) & 0x0000FFFF;
  }

  /**
   * Extract the access type from an I/O control code
   *
   * @param ioctl int
   * @return int
   */
  public final static int getAccessType(int ioctl) {
    return ( ioctl >> 14) & 0x00000003;
  }

  /**
   * Extract the function code from the I/O control code
   *
   * @param ioctl int
   * @return int
   */
  public final static int getFunctionCode(int ioctl) {
    return ( ioctl >> 2) & 0x00000FFF;
  }

  /**
   * Extract the method code from the I/O control code
   *
   * @param ioctl int
   * @return int
   */
  public final static int getMethod(int ioctl) {
    return ioctl & 0x00000003;
  }

  /**
   * Make a control code
   *
   * @param devType int
   * @param func int
   * @param method int
   * @param access int
   * @return int
   */
  public final static int makeControlCode(int devType, int func, int method, int access) {
    return (devType << 16) + (access << 14) + (func << 2) + (method);
  }

  /**
   * Return an I/O control code as a string
   *
   * @param ioctl int
   * @return String
   */
  public final static String asString(int ioctl) {
    StringBuffer str = new StringBuffer();

    str.append("[Func:");
    str.append(getFunctionCode(ioctl));

    str.append(",DevType:");
    str.append(getDeviceType(ioctl));

    str.append(",Access:");
    str.append(getAccessType(ioctl));

    str.append(",Method:");
    str.append(getMethod(ioctl));

    str.append("]");

    return str.toString();
  }
}
